<template>
  <div class="login-page">
    <div class="login-container">    
      <!-- 添加登录方式切换按钮 -->
      <div class="login-tabs">
        <!-- 注意我的注释不能放在标签的内部只能放在外部  -->
        <!-- :class="{ className: condition }"是一种动态类绑定方式 
        注意我的condition可以是一个表达式不要加引号
        如果 condition 为 true，那么 className 类会被添加到元素上，否则不会添加。
        -->
        <!-- 这里就是如果 loginType 等于 'password' 就添加 active 类 
        这个按钮被激活处于激活的样式，以下的短信登录同理-->
        <button 
          class="tab-button"
          :class="{ active: loginType === 'password' }"
          @click="switchToPasswordLogin"
        >
          密码登录
        </button>
        <span class="tab-separator">|</span>
        <button 
          class="tab-button" 
          :class="{ active: loginType === 'sms' }"
          @click="switchToSmsLogin"
        >
          短信登录
        </button>
      </div>
      
      <!-- 密码登录表单 -->
      <!-- v-if 指令用于 条件性地渲染一块内容 ，
        只有当指令的表达式返回 true 时，被指令绑定的元素才会被渲染到 DOM 中；
        当表达式返回 false 时，该元素会被完全从 DOM 中移除。 -->
        <!-- ref 是 Vue.js 的一个内置指令，用于 在组件实例中注册一个引用 ，
        让你可以在 JavaScript 中直接访问和操作 DOM 元素或子组件实例。 
        loginFormRef 实际上是一个 响应式引用对象 ，
        而 loginFormRef.value 才是这个引用 指向的实际内容 。-->
        <!-- :model 是 v-bind:model 的缩写，
        用于 将表单数据与组件实例中的数据对象进行双向绑定 。 -->
        <!-- :rules 用于 为表单定义验证规则 ，是 Element Plus 表单验证功能的核心配置。
        通过这些规则，表单可以自动进行输入验证，并提供相应的错误提示。 -->


  <!-- - 主要使用位置 ： rules 属性 主要 用于 <el-form> 组件，用于定义整个表单的验证规则
- 其他用法 ：也可以直接在单个表单字段（如 <el-form-item> ）上使用 :rules 属性，用于定义该字段的验证规则
- 优先级 ：如果一个字段在 <el-form> 和 <el-form-item> 上都定义了规则，
  那么 <el-form-item> 上的规则会优先生效 -->


<!-- 规则对象中的键名 必须与表单数据对象中的属性名完全对应 - 
使用 :rules 验证规则通常需要先有 :model="form" 数据绑定 。
  1.
当用户输入数据时，数据会更新到 form 对象的对应属性中
- 2.
Element Plus 会根据规则对象中相同的键名找到对应的验证规则-->
<!-- 规则对象中的键名还需要与表单项的 prop 属性值完全对应： -->
<!-- - 
  1.
<el-form> 组件接收 :rules="rules" 属性，获取整个表单的验证规则
  2.
遍历 <el-form> 内部的所有 <el-form-item> 组件
  3.
对于每个 <el-form-item> ，读取其 prop 属性的值
  4.
使用这个值在 rules 对象中查找对应的验证规则
  5.
当该表单项的值发生变化或失去焦点时，使用找到的规则进行验证 -->
      <el-form 
        v-if="loginType === 'password'"
        ref="loginFormRef" 
        :model="form" 
        :rules="rules" 
        class="login-form"
      >
<!-- ### 1.1 v-model 指令
v-model 是 Vue.js 提供的 双向数据绑定指令 ，它可以：
- 将数据从组件实例同步到视图（模板）
- 将用户在视图中的输入同步回组件实例的数据
- 自动处理不同表单元素的事件监听和值设置
### 1.2 :model 指令
:model 是 v-bind:model 的缩写，它只是 单向数据绑定 ，只能：
- 将数据从组件实例同步到视图
- 无法将用户的输入同步回组件实例的数据 -->
<!-- prop="phone" 主要有以下三个核心功能：
1. 1.关联验证规则 ：告诉表单系统这个字段应该使用验证规则中哪个规则进行验证
2. 2.定位数据模型 ：指定要验证的数据在表单模型中的具体属性
3. 3.错误信息显示 ：当验证失败时，确定在哪个表单项下方显示错误信息 -->
<!-- 
1.
表单数据模型 ( :model ) : 绑定到 <el-form> 的数据对象
- 2.
表单项属性 ( prop ) : 指定要验证的具体字段
- 3.
验证规则 ( :rules ) : 定义字段的验证逻辑 -->
        <el-form-item prop="username">
          <el-input 
            v-model=form.username
            placeholder="用户名"
            @input="handleInput('username')"
          >
<!-- 
2.1 <template> 标签
<template> 是一个 无渲染的容器标签 ，用于包裹要插入插槽的内容。它本身不会被渲染到DOM中，只作为内容的容器。
2.2 #prefix 属性
prefix 是 v-slot:prefix 的 简写形式 ，表示这是一个名为 "prefix" 的具名插槽。
- v-slot: 是Vue的指令，用于定义插槽
- prefix 是插槽的名称，用于标识要插入内容的位置
2.3 插槽内容
<el-icon><User /></el-icon> 是要插入到插槽中的具体内容，这里是一个Element Plus的用户图标。 -->
            <template #prefix>
              <el-icon><User /></el-icon>
            </template>
          </el-input>
        </el-form-item>
        
        <el-form-item prop="password">
          <!-- Element Plus 的表单验证系统依赖于 v-model 绑定的数据：
- 验证规则会监听 form.password 的变化
- 当触发验证时，系统会检查 form.password 的当前值是否符合规则
- 如果没有 v-model ，验证系统将无法获取用户的实际输入值 -->
          <el-input 
            v-model=form.password
            type="password" 
            placeholder="密码"
            @input="handleInput('password')"
          >
            <template #prefix>
              <el-icon><Lock/></el-icon>
            </template>
          </el-input>
        </el-form-item>
        
        <!-- 验证码输入框 -->
        <el-form-item prop="captcha">
          <div class="captcha-container">
            <el-input 
              v-model=form.captcha 
              placeholder="验证码"
              @input="handleInput('captcha')"
              class="captcha-input"
            >
              <template #prefix>
                <el-icon><Key/></el-icon>
              </template>
            </el-input>
<!-- 这段代码的逻辑
1. 首先是一个大容器里面有两个小容器
第一个小容器是验证码输入框
第二个小容器是点击获取验证码的按钮 
2. 里面两个容器的显示和我的v-if以及v-else有关，首先对我的v-if进行判断，
如果captchaUrl存在，那么就显示验证码图片，否则就显示点击获取验证码的按钮 
这里面使用到了v-if v-else 还可以多个一起用例如
v-if v-else-if v-else-->
            <div class="captcha-image" @click="getCaptcha">
              <img :src="captchaUrl" alt="验证码" v-if="captchaUrl" />
              <div v-else class="captcha-loading">点击获取验证码</div>
            </div>
          </div>
        </el-form-item>
        
        <!-- 添加记住我选项，位于验证码和登录按钮之间 -->
        <el-form-item>
          <div class="remember-me-wrapper">
            <!-- 在 Vue 中， v-model="form.rememberMe" 即使加了引号仍然能正确工作，这是因为：
1. 1.Vue 模板编译器对指令的属性值有特殊的解析规则
2. 2.它会尝试将带引号的属性值解析为 JavaScript 表达式
3. 3.如果解析成功，就会将其作为表达式处理，而不是字符串字面量 
最好是符合规范不加上引号-->
            <el-checkbox v-model=form.rememberMe class="remember-me-checkbox">记住我</el-checkbox>
          </div>
        </el-form-item>
        
<!-- type="primary" 是一个 静态属性 ，用于设置按钮的样式类型（主题）。 -->
<!-- :loading="isLoading" 是一个 动态属性绑定 （注意前面的冒号 : ），用于控制按钮的加载状态。
  它将按钮的加载状态与 Vue 组件中的 isLoading 变量绑定。 -->
        <!-- 登录按钮 -->
        <el-form-item>
          <el-button 
            type="primary" 
            :loading="isLoading"
            class="login-button"
            @click="onLogin"
          >
            登录
          </el-button>
        </el-form-item>
        
        <div class="login-links">
          <el-link @click="onRegister">注册</el-link>
          <span class="link-separator">|</span>
          <el-link @click="onForgot">忘记密码？</el-link>
        </div>
      </el-form>
      
      <!-- 短信登录表单 -->
      <el-form 
        v-if="loginType === 'sms'"
        ref="smsFormRef" 
        :model="smsForm" 
        :rules="smsRules" 
        class="login-form"
      >
        <el-form-item prop="phone">
            <el-input 
              v-model=smsForm.phone 
              placeholder="请输入手机号"
              @input="handleSmsInput('phone')"
              class="sms-input"
            >
            <template #prefix>
              <span class="country-code">+86</span>
            </template>
            </el-input> 
        </el-form-item>
        
        <!-- 修改后的短信验证码输入框 -->
        <el-form-item prop="smsCode">
          <div class="sms-code-wrapper">
            <el-input 
              v-model=smsForm.code
              placeholder="请输入验证码"
              @input="handleSmsInput('smsCode')"
              class="sms-code-input"
            />
<!-- plain 是 Element Plus 按钮组件的一个布尔类型属性，用于设置按钮为 朴素样式 
 plain 属性最常见的使用场景是 辅助操作按钮 。 -->
 <!-- :disabled 是v-bind:disabled表达式的缩写 v-bind等号右边
  可以接变量 ，也可以接表达式 ，
  对于:class右边还可以接对象例如:calss{样式：条件,.....} 条件满足就添加样式-->
            <el-button 
              type="primary" 
              plain
              :disabled="isSmsCodeSending || countdown > 0"
              @click="getSmsCode"
              class="get-sms-code-btn"
            >
              {{ countdown > 0 ? `${countdown}秒后重试` : '获取验证码' }}
            </el-button>
          </div>
        </el-form-item>
        
        <!-- 登录按钮 -->
        <!-- loading是element-plus ui当中特有的  -->
        <el-form-item>
          <el-button 
            type="primary" 
            :loading="isSmsLoading"
            class="login-button"
            @click="onSmsLogin"
          >
            登录
          </el-button>
        </el-form-item>
        
        <div class="login-links">
          <el-link @click="onRegister">注册</el-link>
          <span class="link-separator">|</span>
          <el-link @click="onForgot">忘记密码？</el-link>
        </div>
      </el-form>
      
      <!-- 将第三方登录移到表单外部，位于最底部 -->
      <div class="third-party-login-container">
        <div class="login-divider">
          <span>其他登录方式</span>
        </div>
        
        <div class="oauth-container">
          <button 
            :disabled="oauthLoading"
            class="gitee-login-btn"
            @click="onGiteeLogin"
          >
          <!-- alt 属性是 HTML 中的一个标准属性，全称为 "alternate text" （替代文本）。
          它用于为图像提供描述性文本，主要目的是在图像无法显示时提供内容替代。 -->
            <img 
              src="@/static/logo_gitee-300x300.jpg" 
              alt="Gitee" 
              class="gitee-logo"
            />
            <span class="gitee-text">使用 Gitee 账号登录</span>
          </button>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted, onUnmounted } from 'vue'
import { User, Lock, Key } from '@element-plus/icons-vue'
import {post, get} from "@/utils/request"
import { useAuthStore } from '@/stores/authStore'
import { useRouter } from 'vue-router'
import { ElMessage } from 'element-plus'
import type { RequestConfig } from '@/utils/request'

// 登录类型状态：'password' 或 'sms'
// - 'password' | 'sms' 表示这个 ref 的值只能是字符串 'password' 或 'sms' 中的一个
// 括号中的 'password' 是传递给 ref() 函数的参数，作为响应式对象的 初始值 ：
const loginType = ref<'password' | 'sms'>('password')

// 密码登录表单数据
const form = ref({
  username: '',
  password: '',
  captcha: '',
  rememberMe: false
})

// 短信登录表单数据
const smsForm = ref({
  phone: '',
  code: ''
})
// Vue 会在组件渲染时，自动将带有 ref="loginFormRef" 属性的 DOM 元素或组件实例
// 赋值给 JavaScript 中同名的 loginFormRef.value 。
const loginFormRef = ref()
const smsFormRef = ref()
// - ef() 函数的括号中 可以写入默认值 ，这个值将作为响应式引用的初始值
// - 可以传递各种类型的默认值，包括基本类型和复杂类型
// - 当不传递参数时， ref() 的默认值为 undefined
// - TypeScript 会根据默认值自动推断 ref 的类型，也可以通过泛型明确指定类型
const isLoading = ref(false)
const isSmsLoading = ref(false)
const captchaUrl = ref('')
const captchaId = ref('')
const oauthLoading = ref(false) // OAuth登录加载状态
const router = useRouter();

// 短信验证码相关状态
const countdown = ref(0)
const isSmsCodeSending = ref(false)
// countdownTimer ：普通变量，存储定时器ID，用于管理定时器的创建和清除
let countdownTimer: number | null = null

// 表单验证规则保持不变
const rules = ref({
  username: [
    { required: true, message: '请输入用户名', trigger: 'blur' }
  ],
  password: [
    { required: true, message: '请输入密码', trigger: 'blur' }
  ],
  captcha: [
    { required: true, message: '请输入验证码', trigger: 'blur' },
    { min: 4, max: 6, message: '验证码长度为4-6位', trigger: 'blur' },
  ]
})

// 短信登录表单验证规则
const smsRules = ref({
  phone: [
    { required: true, message: '请输入手机号', trigger: 'blur' },
    { pattern: /^1[3-9]\d{9}$/, message: '请输入正确的手机号', trigger: 'blur' }
  ],
  code: [
    { required: true, message: '请输入验证码', trigger: 'blur' },
    { min: 4, max: 6, message: '验证码长度为4-6位', trigger: 'blur' }
  ]
})

// 切换到密码登录
const switchToPasswordLogin = () => {
  loginType.value = 'password'
}

// 切换到短信登录
const switchToSmsLogin = () => {
  loginType.value = 'sms'
}

// 组件挂载时先验证记住我功能
onMounted(async () => {
  try {
    // 发送记住我验证请求，并设置ignoreError为true不显示错误信息
    const response = await get('/rememberMe/validate', {}, 
    { ignoreError: true,
      showLoading : false
    } as RequestConfig)
    
    // 如果验证成功，直接跳转到首页
      // 设置认证信息
      const authStore = useAuthStore();
      authStore.setAuth(response);
      router.replace({ name: 'Home' });
      return; // 直接返回，避免继续执行后续代码
  } catch (error) {
    // 验证失败或发生错误，记录日志但不显示错误信息
    console.log('记住我验证失败，继续加载登录页面:', error)
  }
  
  if (loginType.value === 'password') {
    getCaptcha()
  }
})

// 组件卸载时清除定时器
// 防止内存泄漏的重要保障 
// 它确保在组件卸载时清除所有活动的定时器，避免资源浪费和潜在的应用错误。
onUnmounted(() => {
  if (countdownTimer) {
    clearInterval(countdownTimer)
  }
})

// 获取验证码函数保持不变
const getCaptcha = async () => {
  try {
    // 清空之前的验证码数据
    form.value.captcha = ''
    captchaUrl.value = ''
    //在我提交登录的时候会用到这个验证码ID
    captchaId.value = ''
    
    // 调用后端接口获取验证码
    //这个response是我的后端返回对象当中的data字段
    const response = await get('/getCaptcha',{},
    {showLoading : false} as RequestConfig)
    
    // 根据您的描述，后端返回的是一个对象，包含验证码id和验证码图片的base64编码
    // 假设返回格式为: { code: 200, data: { captchaId: 'xxx', captchaImage: 'base64字符串' } }
    if (response) {
      // 存储验证码ID
      captchaId.value = response.captchaId || ''
      
      // 处理验证码图片（base64格式）
      // 如果后端返回的图片数据不包含'data:image/png;base64,'前缀，则需要添加
      // 当浏览器遇到这种 Data URL 时，会执行以下步骤来显示图片：
// Data URL （也称为 Data URI）的一种，
// 它允许将小文件（如图片）直接嵌入到 HTML 或 CSS 中，而不需要单独的文件请求
// ### 2.1 解析 Data URL 结构
// 1. 1.
//    浏览器首先识别字符串以 data: 开头，确定这是一个 Data URL
// 2. 2.
//    解析 MIME 类型（ image/png ），了解数据的类型
// 3. 3.
//    确认编码方式（ base64 ）
// 4. 4.
//    提取 Base64 编码的实际数据部分（ ${base64Data} ）
      const base64Data = response.captchaCode || ''
      captchaUrl.value = base64Data.startsWith('data:image') 
        ? base64Data 
        : `data:image/png;base64,${base64Data}`
    } else {
      console.error('获取验证码失败', response)
    }
  } catch (error) {
    console.error('获取验证码失败', error)
  }
}

// 获取短信验证码
const getSmsCode = async () => {
  if (!smsFormRef.value) return
  
  try {
    // 验证手机号
// validateField 验证单个或多个指定字段 只需要验证表单部分字段的情况 
// validate 验证整个表单 提交表单前的完整验证
// resetFields 重置表单字段值和验证状态 取消表单编辑时
// clearValidate 清除表单或指定字段的验证状态 需要手动清除验证提示时
    await smsFormRef.value.validateField('phone')
    
    isSmsCodeSending.value = true
    
    // 调用后端接口发送短信验证码
    await post('/sendSmsCode', { phone: smsForm.value.phone })
    // 开始倒计时
    startCountdown()
  } catch (error) {
    console.error('发送验证码失败', error)
  } finally {
    //注意最后我需要将我的isSmsCodeSending.value设置为false，让我下次还可以发送验证码
    isSmsCodeSending.value = false
  }
}

// 开始倒计时
const startCountdown = () => {
  countdown.value = 120
  
  // 清除之前的定时器
  //虽然我在下面也清楚了countdownTimer，但是为了保险起见，我还是在这清除一下
  //因为我的这个定时器如果不清除他会一直存在并且运行
  if (countdownTimer) {
    clearInterval(countdownTimer)
  }
  
  // 设置新的定时器
  // setInterval 重复执行指定函数 周期性执行，直到被清除
  // setTimeout 延迟指定时间后执行一次函数 只执行一次，除非在回调中再次调用
  countdownTimer = window.setInterval(() => {
    if (countdown.value > 0) {
      countdown.value--
    } else {
      if (countdownTimer) {
        clearInterval(countdownTimer)
        countdownTimer = null
      }
    }
  }, 1000)
}
//以下两个函数的作用都是，如果用户正在输入框当中输入内容那么我的错误提示就被清除
const handleInput = (field: string) => {
  if (loginFormRef.value) {
    loginFormRef.value.clearValidate(field)
  }
}
// 处理短信登录表单输入
const handleSmsInput = (field: string) => {
  if (smsFormRef.value) {
    smsFormRef.value.clearValidate(field)
  }
}

const onLogin = async () => {
  if (!loginFormRef.value) return  
  
  try {
    await loginFormRef.value.validate()
    
    // 检查是否有验证码ID
    //我的后端可能并没有返回验证码ID，所以我需要检查一下，
    // 如果没有验证码ID，我就重新获取验证码
    if (!captchaId.value) {
      console.error('验证码ID不存在，请重新获取验证码')
      getCaptcha()
      return
    }
    //表示我现在正在登录当中，所以我需要将我的isLoading.value设置为true
    isLoading.value = true
    
    // 登录请求中包含用户名、密码、验证码和记住我状态
    // 我的axios响应拦截器最后返回的是我的后端返回的对象当中的数据字段data
    const token = await post('/login', {
      loginAct: form.value.username,
      loginPwd: form.value.password,
      captchaId: captchaId.value,  // 验证码ID
      captchaCode: form.value.captcha,  // 用户输入的验证码
      rememberMe: form.value.rememberMe  // 添加记住我状态到请求中
    })
    //成功登录之后将我的访问令牌存储进我的状态管理当中
    const authStore = useAuthStore();
    authStore.setAuth(token);
    //对于我的登录页面选择replace而不是push，
    // 是因为我不希望用户在登录成功后点击返回按钮能够回到登录页面
    router.replace({ name: 'Home' });
  } catch (error: unknown) { 
    getCaptcha()
    
    if (error instanceof Error) {
      console.log(error.message || '表单验证失败');
    } else {
      console.log(String(error) || '未知错误');
    }
  } finally{
    //最后无论是登录成功还是失败我需要将我的isLoading.value设置为false
    //使我仍然可以登录
    isLoading.value = false
  }
}

// 短信登录
const onSmsLogin = async () => {
  if (!smsFormRef.value) return  
  
  try {
    await smsFormRef.value.validate()
    
    isSmsLoading.value = true
    
    // 发送短信登录请求
    const response = await post('/smsLogin', {
      phone: smsForm.value.phone,
      code: smsForm.value.code,
    })
    const authStore = useAuthStore();
    authStore.setAuth(response);
    router.replace({ name: 'Home' });
  } catch (error: unknown) { 
    if (error instanceof Error) {
      console.log(error.message || '表单验证失败');
    } else {
      console.log(String(error) || '未知错误');
    }
  }finally{
    isSmsLoading.value = false
  }
}

const onRegister = () => {
  router.push({ name: 'Register' });
}

const onForgot = () => {
  router.push({ name: 'ForgotPwd' });
}

// Gitee登录
const onGiteeLogin = async () => {
  try {
    oauthLoading.value = true
    // 获取Gitee OAuth配置
    const clientId = import.meta.env.VITE_GITEE_CLIENT_ID
    const redirectUri = import.meta.env.VITE_GITEE_REDIRECT_URI
    const scope = import.meta.env.VITE_GITEE_SCOPE || 'user_info'
    
    // 添加环境变量检查
    if (!clientId || !redirectUri) {
      console.error('Gitee OAuth配置不完整，请检查.env文件')
      ElMessage.error('Gitee登录配置未完成，请联系管理员')
      oauthLoading.value = false
      return
    }
    
    // 生成随机状态值，用于防止CSRF攻击
    const state = Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15)
    
    // 存储state到sessionStorage，供回调页面验证使用
    //这个state的作用如下
//我的恶意网站可能有某个图片或者按钮，而这个图片和按钮是指向我的Gitee登录页面的
//假设在我的电脑上我的gitee已经登录成功了，
//这个时候就会直接授权成功重定向到我gitee当中规定的回调页面
//如果在我的回到页面当中不检测state，那么我就会想我的后端或者本地直接
//携带授权码向我的gitee发送访问资源请求然后生成会话
//这个时候就会导致我的会话被攻击，我的恶意人员就可以
// 使用这个会话可能是session也可能是jwt,去访问我该应用的资源了
//所以我需要在我的回调页面当中检测state，
//如果state不匹配，那么我就不会向我的后端或者本地自己向gitee发送请求生成对应的会话信息
    sessionStorage.setItem('gitee_oauth_state', state)
    
    // 构造Gitee授权URL
//encodeURIComponent 函数会将字符串中的所有非字母数字字符（除了少数几个例外，如 - 、 _ 、 . 、 ! 、 ~ 、 * 、 ' 、 ( 、 ) ）
// 转换为 UTF-8 编码的转义序列，格式为 %xx ，其中 xx 是字符的十六进制表示。
//如果不进行编码，其中的特殊字符（如 ? 、 = 、 / 等）
//可能会被误解为 URL 的一部分，导致重定向失败或重定向到错误的地址。


//encodeURI 是一个用于编码完整 URI 的 JavaScript 函数，
// 它保留了 URL 结构中具有特殊含义的字符（如 :/?#&=+$,; ），
// 只编码那些在 URL 中不允许出现的字符。
//encodeURI ：仅编码 URL 中严格不允许出现的字符（如中文、空格等），
// 但保留 URL 结构中的特殊字符（如 :/?#&=+$,; ）
//这种设计使得它特别适合用于处理完整的 URL 字符串，保持 URL 的结构完整性


//如果不使用 encodeURIComponent 编码， 我后面参数对应的值当中可能存在 
//? 、 & 、 = 等字符会被解析为整个 URL 的一部分，导致参数错误拆分。
//此时我应该使用encodeURIComponent
    const giteeAuthUrl = `https://gitee.com/oauth/authorize?client_id=${clientId}&redirect_uri=${encodeURIComponent(redirectUri)}&response_type=code&state=${state}&scope=${encodeURIComponent(scope)}`
    
    // 跳转到Gitee授权页面
    window.location.href = giteeAuthUrl
  } catch (error) {
    console.error('Gitee登录失败', error)
    ElMessage.error('Gitee登录失败，请重试')
    oauthLoading.value = false
  }
}
</script>

<style scoped>
.login-page {
  min-height: 100vh;
  display: flex;
  justify-content: center;
  align-items: center;
  background-color: #eef2f6;
}

.login-container {
  width: 400px;
  padding: 30px;
  background-color: white;
  border-radius: 8px;
  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
}

.login-title {
  margin-bottom: 25px;
  text-align: center;
}

.title-text {
  font-size: 28px;
  font-weight: bold;
}

.login-form {
  width: 100%;
}

/* 登录按钮样式 */
.login-button {
  width: 100%;
  height: 45px;
  font-size: 18px;
  font-weight: 500;
  padding: 0;
  margin-bottom: 20px;
  background-color: #ff6700; /* 橙色登录按钮，仿照参考样式 */
  border-color: #ff6700;
}

.login-button:hover {
  background-color: #e65c00;
  border-color: #e65c00;
}

/* 登录链接样式 */
.login-links {
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 15px;
  margin-top: 20px;
}

.link-separator {
  color: #dcdfe6;
}

:deep(.el-link) {
  font-size: 14px;
  color: #606266;
}

:deep(.el-link:hover) {
  color: #409eff;
}

/* 验证码样式 */
.captcha-container {
  display: flex;
  align-items: center;
  gap: 10px;
}

.captcha-input {
  flex: 1;
}

.captcha-image {
  width: 120px;
  height: 42px;
  cursor: pointer;
  border: 1px solid #dcdfe6;
  border-radius: 6px;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
}

.captcha-image img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.captcha-loading {
  font-size: 12px;
  color: #909399;
}

/* 解决输入框嵌套效果 */
:deep(.el-input__inner) {
  font-size: 16px;
  padding: 12px 15px;
  border-radius: 6px;
  height: 42px;
  border-width: 1px;
  box-shadow: none !important;
  border-color: #dcdfe6;
}

/* 第三方登录容器样式 - 移到最底部 */
.third-party-login-container {
  margin-top: 30px;
  width: 100%;
}

/* 分割线样式 */
.login-divider {
  position: relative;
  text-align: center;
  margin-bottom: 20px;
  height: 16px;
  line-height: 16px;
}

.login-divider span {
  font-size: 14px;
  color: #999;
  background: #fff;
  padding: 0 20px;
  position: relative;
  z-index: 1;
}

.login-divider::before {
  content: '';
  position: absolute;
  top: 50%;
  left: 0;
  right: 0;
  height: 1px;
  background-color: #e0e0e0;
  z-index: 0;
}

/* Gitee登录按钮样式 */
.oauth-container {
  display: flex;
  justify-content: center;
}

.gitee-login-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  padding: 10px 20px;
  background-color: #2e3436;
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
  font-size: 14px;
  transition: background-color 0.3s;
}

.gitee-login-btn:hover {
  background-color: #3c3f41;
}

.gitee-login-btn:disabled {
  background-color: #cccccc;
  cursor: not-allowed;
}

/* Gitee图标样式 */
.gitee-logo {
  width: 20px;
  height: 20px;
  margin-right: 8px;
  border-radius: 2px;
}

.gitee-text {
  font-size: 14px;
}

/* 记住我选项样式 - 精确匹配图片 */
.remember-me-wrapper {
  display: flex;
  align-items: center;
  margin-bottom: 15px;
}

.remember-me-checkbox {
  font-size: 14px;
  color: #606266;
  cursor: pointer;
}

.remember-me-checkbox .el-checkbox__label {
  padding-left: 6px;
}

/* 登录按钮样式 - 调整为橙色，与参考图片一致 */
.login-button {
  width: 100%;
  height: 45px;
  font-size: 18px;
  font-weight: 500;
  padding: 0;
  margin-bottom: 20px;
  background-color: #ff6700; /* 橙色登录按钮 */
  border-color: #ff6700;
}

.login-button:hover {
  background-color: #e65c00;
  border-color: #e65c00;
}

/* 登录方式切换按钮样式 */
.login-tabs {
  display: flex;
  justify-content: center;
  align-items: center;
  margin-bottom: 25px;
  padding-bottom: 15px;
  border-bottom: 1px solid #f0f0f0;
}

.tab-button {
  background: none;
  border: none;
  font-size: 16px;
  color: #606266;
  cursor: pointer;
  padding: 0 15px;
  position: relative;
  transition: color 0.3s;
}

.tab-button:hover {
  color: #409eff;
}

.tab-button.active {
  color: #ff6700;
  font-weight: 500;
}

.tab-button.active::after {
  content: '';
  position: absolute;
  bottom: -16px;
  left: 50%;
  transform: translateX(-50%);
  width: 24px;
  height: 2px;
  background-color: #ff6700;
}

.tab-separator {
  color: #dcdfe6;
}

/* 自定义记住我复选框选中状态样式 */
:deep(.remember-me-checkbox .el-checkbox__input.is-checked .el-checkbox__inner) {
  background-color: #ff6700; /* 橙色背景 */
  border-color: #ff6700; /* 橙色边框 */
}

:deep(.remember-me-checkbox .el-checkbox__input.is-checked .el-checkbox__inner::after) {
  border-color: #ffffff; /* 白色对勾 */
}

/* 短信登录样式 */
/* 手机号输入框样式 */
:deep(.sms-input) {
  position: relative;
}

:deep(.sms-input .el-input__wrapper) {
  box-shadow: none !important;
}

:deep(.sms-input .el-input__prefix) {
  background-color: #f5f7fa;
  border-right: 1px solid #dcdfe6;
  padding: 0 10px;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  margin-right: 0 !important;
  width: 50px;
  border-radius: 6px 0 0 6px;
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  z-index: 1;
}

:deep(.sms-input .el-input__inner) {
  border-radius: 6px !important;
  padding-left: 60px !important; /* 为前缀留出空间 */
  border: 1px solid #dcdfe6 !important;
}

.country-code {
  color: #606266;
  font-size: 14px;
  font-weight: 500;
  text-align: center;
  width: 100%;
}

/* 短信验证码样式 */
.sms-code-wrapper {
  display: flex;
  align-items: center;
  gap: 10px;
}

.sms-code-input {
  flex: 1;
}

.get-sms-code-btn {
  min-width: 120px;
  height: 42px;
  background-color: #fff;
  color: #ff6700;
  border: 1px solid #ff6700;
  border-radius: 6px;
  font-size: 14px;
  padding: 0 12px;
  transition: all 0.3s;
}

.get-sms-code-btn:hover:not(:disabled) {
  background-color: #fff7e6;
  color: #ff6700;
  border-color: #ff6700;
}

.get-sms-code-btn:disabled {
  color: #c0c4cc;
  border-color: #dcdfe6;
  background-color: #f5f7fa;
  cursor: not-allowed;
}
</style>

/* 添加页面加载样式 */
.loading-overlay {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background-color: rgba(255, 255, 255, 0.8);
  display: flex;
  justify-content: center;
  align-items: center;
  z-index: 9999;
}

.loading-content {
  text-align: center;
}